package com.leenmvc.core.web.controller;

import com.leenmvc.core.annotation.Note;
import com.leenmvc.core.base.BaseController;
import com.leenmvc.core.security.User;
import com.leenmvc.core.security.entity.core.SysFileUpload;
import com.leenmvc.core.security.service.core.SysFileUploadService;
import com.leenmvc.core.utils.file.UploadManager;
import com.leenmvc.core.base.result.Result;
import io.minio.MinioClient;
import io.minio.errors.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.xmlpull.v1.XmlPullParserException;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;

/**
 * 文件上传下载控制器
 *
 * @author Cloud
 */
@RestController
@RequestMapping("system/oss")
public class SysFileUploadController extends BaseController<SysFileUpload> {

    // 配置上传服务器地址，公钥，私钥
    private static String url = "http://192.168.3.235:29000/";
    private static String accessKey = "minioadmin";
    private static String secretKey = "minioadmin";

    @Autowired
    private SysFileUploadService sysFileUploadService;

    @PostMapping("write")
    @RequiresPermissions("system:file:write")
    @Note("配合前端使用接口来修改文件实现动态文件控制")
    public Result write(){
        return new Result();
    }

    @GetMapping("files")
    @RequiresPermissions("system:oss:files")
    @Note("获取该用户已经上传的文件")
    public Result getFiles() {
        Long id = User.getUser().getId();
        try{
            MinioClient minioClient = new MinioClient(url,accessKey,secretKey);
        } catch (InvalidEndpointException e) {
            e.printStackTrace();
        } catch (InvalidPortException e) {
            e.printStackTrace();
        }
        List<SysFileUpload> fileUploads = listBySqlKey("getListByCreator", "id", id);

        return new Result().ok(fileUploads);
    }

    @PostMapping("upload")
    @RequiresPermissions("system:oss:upload")
    @Note("上传文件到minio服务器")
    public Result uploadFiles(MultipartFile file) {
        try(InputStream is = new BufferedInputStream(file.getInputStream())){
            Long id = User.getUser().getId();
            // 客户端
            MinioClient minioClient = new MinioClient(url, accessKey, secretKey);
            String buckId = id.toString();
            String filename = file.getOriginalFilename();
            String contentType = file.getContentType();
            if (!minioClient.bucketExists(buckId)) {
                minioClient.makeBucket(buckId);
            }
            UploadManager.uploadToLocal(file);
            minioClient.putObject(buckId,filename,is,contentType);
            return new Result().ok("上传成功！");
        }
        catch (Exception ex) {
            ex.printStackTrace();
            return new Result().info("上传失败!");
        }
    }


    @GetMapping("download")
    @RequiresPermissions("system:oss:download")
    @Note("从服务器下载文件到本地")
    public Result downloadFiles(@RequestParam("filename") String filename, HttpServletResponse httpResponse) throws InvalidPortException, InvalidEndpointException, UnsupportedEncodingException {
        MinioClient minioClient = new MinioClient(url,accessKey,secretKey);
        Long id = User.getUser().getId();
        String buckId = id.toString();
        httpResponse.reset();
        httpResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        httpResponse.setContentType("application/x-msdownload");
        httpResponse.setCharacterEncoding("utf-8");
        try(InputStream ism = new BufferedInputStream(minioClient.getObject(buckId, filename));
            OutputStream osm = new BufferedOutputStream(httpResponse.getOutputStream());) {
            minioClient.statObject(buckId, filename);
            byte buf[] = new byte[1024];
            int length = 0;
            while ((length = ism.read(buf))>0) {
                osm.write(buf,0, length);
            }
        } catch (MinioException ex) {
            ex.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return new Result();
    }

    @DeleteMapping("delete")
    @RequiresPermissions("system:oss:del")
    @Note("删除用户上传过的文件")
    public void delete(@RequestParam("id") String id) {
        Long ids = User.getUser().getId();
        String buckId = ids.toString();
        List<SysFileUpload> fileList = listBySqlKey("getListById", "id", id);
        SysFileUpload sysFileUpload = fileList.get(0);
        String filename = sysFileUpload.getOriginalName();
        try {
            MinioClient minioClient = new MinioClient(url, accessKey, secretKey);
            minioClient.statObject(buckId, filename);
            minioClient.removeObject(buckId, filename);
        } catch (InvalidBucketNameException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InsufficientDataException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoResponseException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        } catch (ErrorResponseException e) {
            e.printStackTrace();
        } catch (InternalException e) {
            e.printStackTrace();
        } catch (InvalidArgumentException e) {
            e.printStackTrace();
        } catch (InvalidResponseException e) {
            e.printStackTrace();
        } catch (InvalidPortException e) {
            e.printStackTrace();
        } catch (InvalidEndpointException e) {
            e.printStackTrace();
        }
        sysFileUploadService.deleteById(id);
    }

    @Override
    public boolean deleteById(Object id) {
        return super.deleteById(id);
    }
}
